import optimizeCallback from './optimizeCallback'
import isArrayLike from '../util/isArrayLike'

function createReduce(dir) {
  function reducer(obj, iteratee, memo, initial) {
    const keys = !isArrayLike(obj) && Object.keys(obj)
    const length = (keys || obj).length
    let index = dir > 0 ? 0 : length - 1

    if (!initial) {
      memo = keys ? obj[keys[index]] : obj[index]
      index += dir
    }

    for (let i = index; i >= 0 && i < length; i += dir) {
      const currentKey = keys ? keys[i] : i
      memo += iteratee(memo, obj[currentKey], currentKey, obj)
    }

    return memo
  }

  return function (obj, iteratee, memo, context) {
    const initial = arguments.length >= 3
    iteratee = optimizeCallback(iteratee, context, 4)

    return reducer(obj, iteratee, memo, initial)
  }
}

export default createReduce
